package com.lzw.main;

import com.lzw.app.InstanceRepository;
import com.lzw.constant.ResponseConstant;
import com.lzw.app.Instance;
import com.lzw.app.ServerApp;
import com.lzw.data.AppRepository;
import com.lzw.utils.DateUtils;
import com.lzw.utils.LogUtils;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 主线程：
 *      监听请求，启动任务线程，执行并给出响应
 * @author LZW
 */
public class ListenerThread extends Thread {
    private ServerApp serverApp;
    private ServerSocket serverSocket;

    public ListenerThread(ServerSocket serverSocket, ServerApp serverApp) {
        this.serverSocket = serverSocket;
        this.serverApp = serverApp;
    }

    @Override
    public void run() {
        while (true) {
            StringBuilder sb = new StringBuilder();
            try {
                //监听请求
                Socket accept = this.serverSocket.accept();
                InputStream inputStream = accept.getInputStream();
                //打印接受监听的日志
                LogUtils.printLogAccepted(sb);
                OutputStream outputStream = accept.getOutputStream();
                //封装为字符流
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
                //接收头信息
                String head = br.readLine();
                if ("add".equals(head)) {
                    //表示需要添加实例(注册)
                    LogUtils.printLogAdd(sb);
                    respStatus(bw, ResponseConstant.RESP_OK);
                    ObjectInputStream ois = new ObjectInputStream(inputStream);
                    Instance instance = (Instance) ois.readObject();
                    //执行注册
                    AppRepository appRepository = serverApp.getAppRepository();
                    appRepository.registerInstance(instance);
                    appRepository.resetLastPing(instance);
                    //打印注册成功的日志
                    LogUtils.printLogInstanceRegisterSuccess(instance, sb);
                    respStatus(bw, ResponseConstant.RESP_SUCCESS);
                } else if ("ping".equals(head)) {
                    //表示ping请求(续约)
                    LogUtils.printLogPing(sb);
                    respStatus(bw, ResponseConstant.RESP_OK);
                    //接收续约实例
                    ObjectInputStream ois = new ObjectInputStream(inputStream);
                    Instance instance = (Instance) ois.readObject();
                    //执行续约
                    AppRepository appRepository = serverApp.getAppRepository();
                    AppRepository serverRepository = serverApp.getServerRepository();
                    appRepository.resetLastPing(instance);
                    serverRepository.resetLastPing(instance);
                    //打印续约成功的日志
                    LogUtils.printLogRenewSuccess(instance, sb);
                    respStatus(bw, ResponseConstant.RESP_PONG);
                } else if ("fetch".equals(head)) {
                    //获取订阅的实例
                    LogUtils.printLogFetch(sb);
                    respStatus(bw, ResponseConstant.RESP_OK);
                    ObjectInputStream ois = new ObjectInputStream(inputStream);
                    Instance instance = (Instance) ois.readObject();
                    //准备订阅数据
                    InstanceRepository repository = new InstanceRepository();
                    AppRepository appRepository = serverApp.getAppRepository();
                    repository.setAppRepository(appRepository);
                    //执行订阅
                    ObjectOutputStream oos = new ObjectOutputStream(outputStream);
                    oos.writeObject(repository);
                    oos.flush();
                    //打印订阅成功的日志
                    LogUtils.printLogFetchSuccess(instance, "SUCCESS", sb);
                    respStatus(bw, ResponseConstant.RESP_SUCCESS);
                } else if ("lzw".equals(head)) {
                    //其他注册中心的集群注册
                    LogUtils.printLogServerAdd(sb);
                    respStatus(bw, ResponseConstant.RESP_OK);
                    ObjectInputStream ois = new ObjectInputStream(inputStream);
                    Instance instance = (Instance) ois.readObject();
                    //执行注册
                    AppRepository serverRepository = serverApp.getServerRepository();
                    serverRepository.registerInstance(instance);
                    serverRepository.resetLastPing(instance);
                    //打印注册成功的日志
                    LogUtils.printLogServerRegisterSuccess(instance, sb);
                    respStatus(bw, ResponseConstant.RESP_SUCCESS);
                } else {
                    LogUtils.printLogBadRequest(sb);
                    respStatus(bw, ResponseConstant.RESP_ERROR);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println(sb.toString());
            }
        }
    }

    private void respStatus(BufferedWriter bw, String status) throws IOException {
        bw.write(status);
        bw.newLine();
        bw.flush();
    }

    private void respObject(ObjectOutputStream oos, Object object) throws IOException {
        oos.writeObject(object);
        oos.flush();
    }
}
